package com.wave.wavesystem.business.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.wave.wavesystem.business.mapper.DeptMapper;
import com.wave.wavesystem.business.mapper.UserDeptMapper;
import com.wave.wavesystem.business.mapper.UserMapper;
import com.wave.wavesystem.business.pojo.dto.userRelation.UserDeptDTO;
import com.wave.wavesystem.business.pojo.entity.DeptEntity;
import com.wave.wavesystem.business.pojo.entity.UserDeptEntity;
import com.wave.wavesystem.business.pojo.entity.UserEntity;
import com.wave.wavesystem.business.pojo.vo.DeptVO;
import com.wave.wavesystem.business.service.UserDeptService;
import wave.common.pojo.entity.Query;
import com.wave.wavesystem.common.util.Condition;
import com.wave.wavesystem.common.util.Func;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;

/**
 * @author 夕下风波
 * @date 2025-02-02
 * @description 用户-部门关联表 业务层接口
 */
@Service
public class UserDeptServiceImpl extends ServiceImpl<UserDeptMapper, UserDeptEntity> implements UserDeptService {

    @Resource
    private DeptMapper deptMapper;

    @Resource
    private UserMapper userMapper;

    @Override
    public boolean batchSave(UserDeptDTO userDepts) {
        List<Long> userIds = Func.strToLongList(userDepts.getUserIds());
        if (Func.isEmpty(userIds)) {
            return true;
        }
        List<UserDeptEntity> saveUserDept = userIds.stream().
                map(item -> new UserDeptEntity(item, userDepts.getDeptId())).toList();
        return this.saveBatch(saveUserDept);
    }

    @Override
    public List<DeptVO> userDepts(Long userId) {
        List<UserDeptEntity> userDepts = this.list(QueryChain.of(UserDeptEntity.class)
                .eq(UserDeptEntity::getUserId, userId));
        if (Func.isEmpty(userDepts)) return Collections.emptyList();
        List<Long> deptIds = userDepts.stream().map(UserDeptEntity::getDeptId).toList();
        List<DeptEntity> deptEntities = deptMapper.selectListByIds(deptIds);
        if (Func.isEmpty(deptEntities)) return Collections.emptyList();
        return deptEntities.stream().map(item -> {
            DeptVO deptVO = new DeptVO();
            BeanUtils.copyProperties(item, deptVO);
            return deptVO;
        }).toList();
    }

    @Override
    public Page<UserEntity> deptUsersPage(Long deptId, Query query) {
        QueryChain<UserDeptEntity> queryChain = QueryChain.of(UserDeptEntity.class)
                .eq(UserDeptEntity::getDeptId, deptId);
        Page<UserDeptEntity> relationPage = this.mapper.paginate(Condition.getPage(query), queryChain);
        if (Func.isEmpty(relationPage.getRecords())) return new Page<>();
        List<Long> userIds = relationPage.getRecords().stream().map(UserDeptEntity::getUserId).toList();
        List<UserEntity> userEntities = userMapper.selectListByIds(userIds);
        if (Func.isEmpty(userEntities)) return new Page<>();
        Page<UserEntity> userPage = new Page<>(query.getPageNum(), query.getPageSize());
        userPage.setTotalRow(relationPage.getTotalRow());
        userPage.setRecords(userEntities);
        return userPage;
    }

    @Override
    public List<DeptEntity> userDeptsList(Long userId) {
        List<UserDeptEntity> userDeptEntities = this.mapper.selectListByQuery(QueryChain.of(UserDeptEntity.class)
                .eq(UserDeptEntity::getUserId, userId));
        if (Func.isEmpty(userDeptEntities)) return Collections.emptyList();
        List<Long> deptIds = userDeptEntities.stream().map(UserDeptEntity::getDeptId).toList();
        return deptMapper.selectListByQuery(QueryChain.of(DeptEntity.class)
                .in(DeptEntity::getId, deptIds));
    }

    @Override
    public Boolean save(UserDeptDTO userDept) {
        UserDeptEntity userDeptEntity = new UserDeptEntity(userDept.getUserId(), userDept.getDeptId());
        this.save(userDeptEntity);
        List<UserDeptEntity> userDeptEntities = this.list(QueryChain.of(UserDeptEntity.class)
                .eq(UserDeptEntity::getUserId, userDept.getUserId()));
        if (Func.isEmpty(userDeptEntities)) return true;
        List<Long> deptIds = userDeptEntities.stream().map(UserDeptEntity::getDeptId).toList();
        StringBuilder sb = new StringBuilder();
        deptIds.forEach(item -> sb.append(item).append(","));
        String deptIdsStr = sb.deleteCharAt(sb.length() - 1).toString();
        UserEntity user = new UserEntity();
        user.setId(user.getId());
        user.setDepts(deptIdsStr);
        return userMapper.update(user) > 0;
    }

    @Override
    public List<UserEntity> notInDeptUser(Long deptId) {
        List<UserDeptEntity> deptUsers = this.mapper.selectListByQuery(QueryChain.of(UserDeptEntity.class)
                .eq(UserDeptEntity::getDeptId, deptId));
        if (Func.isEmpty(deptUsers)) {
            return userMapper.selectAll();
        }
        List<Long> deptUserIds = deptUsers.stream().map(UserDeptEntity::getUserId).toList();
        return userMapper.selectListByQuery(QueryChain.of(userMapper)
                .notIn(UserEntity::getId, deptUserIds));
    }

    @Override
    public Boolean kickOutDept(UserDeptDTO userDepts) {
        List<Long> userId = Func.strToLongList(userDepts.getUserIds());
        return this.remove(QueryChain.of(UserDeptEntity.class)
                .eq(UserDeptEntity::getDeptId, userDepts.getDeptId())
                .in(UserDeptEntity::getUserId, userId));
    }

}
